package com.icesoft.base.manager.service.security;

import com.icesoft.base.manager.base.BaseService;
import com.icesoft.base.manager.entity.security.*;
import com.icesoft.base.manager.helper.PageParam;
import com.icesoft.base.manager.helper.QueryBuilderUtils;
import com.icesoft.base.manager.security.suppose.IUserDetailsService;
import com.icesoft.core.dao.criteria.Page;
import com.icesoft.core.dao.criteria.QueryBuilder;
import lombok.AllArgsConstructor;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@AllArgsConstructor
public class SysRoleService extends BaseService<SysRole> {
    private final RelSysUserRoleService relSysUserRoleService;
    private final RelSysRoleAuthorityService relSysRoleAuthorityService;
    private final RelSysRoleMenuService relSysRoleMenuService;
    private final RelSysRoleOrgService roleOrgService;

    public SysRole findByName(String name) {
        return unique(QueryBuilder.get("name", name));
    }

    public Page<SysRole> page(HttpServletRequest request, SysRole queryParam, String search, PageParam pageParam) {
        QueryBuilder queryBuilder = QueryBuilder.get();
        QueryBuilderUtils.addRequestParam(queryBuilder, request, queryParam);
        QueryBuilderUtils.addSearchParam(queryBuilder, search, new String[]{"name"});
        return page(queryBuilder, pageParam);
    }

    public List<SysRole> findByUserId(int userId) {
        if (userId == 0) {
            return new ArrayList<>();
        }
        QueryBuilder queryBuilder = QueryBuilder.get()
                .joinOn(RelSysUserRole.class, "ur", "roleId")
                .andEq("ur.userId", userId);
        return find(queryBuilder);
    }

    @Transactional
    public void updateRoleMenu(int roleId, int[] menuIds) {
        List<RelSysRoleMenu> relSysRoleMenus = relSysRoleMenuService.findByRoleId(roleId);
        List<Integer> menuIdList = Arrays.stream(menuIds).boxed().collect(Collectors.toList());
        for (RelSysRoleMenu relSysRoleMenu : relSysRoleMenus) {
            if (!menuIdList.contains(relSysRoleMenu.getMenuId())) {
                relSysRoleMenuService.delete(relSysRoleMenu);
            } else {
                menuIdList.remove(new Integer(relSysRoleMenu.getMenuId()));
            }
        }
        for (int menuId : menuIdList) {
            RelSysRoleMenu rm = new RelSysRoleMenu();
            rm.setMenuId(menuId);
            rm.setRoleId(roleId);
            relSysRoleMenuService.create(rm);
        }

    }

    @Transactional
    public void updateRoleAuthority(int roleId, int[] authorityIds) {
        List<RelSysRoleAuthority> roleAuthorities = relSysRoleAuthorityService.findByRoleId(roleId);
        List<Integer> authorityIdList = Arrays.stream(authorityIds).boxed().collect(Collectors.toList());
        for (RelSysRoleAuthority relSysRoleAuthority : roleAuthorities) {
            if (!authorityIdList.contains(relSysRoleAuthority.getAuthorityId())) {
                relSysRoleAuthorityService.delete(relSysRoleAuthority);
            } else {
                authorityIdList.remove(new Integer(relSysRoleAuthority.getAuthorityId()));
            }
        }
        for (Integer authorityId : authorityIdList) {
            RelSysRoleAuthority relSysRoleAuthority = new RelSysRoleAuthority();
            relSysRoleAuthority.setRoleId(roleId);
            relSysRoleAuthority.setAuthorityId(authorityId);
            relSysRoleAuthorityService.create(relSysRoleAuthority);
        }
    }

    @Transactional
    public void updateRoleOrg(int roleId, int[] orgIds) {
        List<RelSysRoleOrg> roleAuthorities = roleOrgService.findByRoleId(roleId);
        List<Integer> orgIdList = Arrays.stream(orgIds).boxed().collect(Collectors.toList());
        for (RelSysRoleOrg roleRog : roleAuthorities) {
            if (!orgIdList.contains(roleRog.getOrgId())) {
                roleOrgService.delete(roleRog);
            } else {
                orgIdList.remove(new Integer(roleRog.getOrgId()));
            }
        }
        for (Integer orgId : orgIdList) {
            RelSysRoleOrg roleOrg = new RelSysRoleOrg();
            roleOrg.setRoleId(roleId);
            roleOrg.setOrgId(orgId);
            roleOrgService.create(roleOrg);
        }
    }

    @Transactional
    public void saveUserRole(int userId, String username, int[] roleIds) {
        List<RelSysUserRole> roleAuthorities = relSysUserRoleService.findByUserId(userId);
        Map<Integer, RelSysUserRole> oldMap = roleAuthorities.stream().collect(Collectors.toMap(RelSysUserRole::getRoleId, Function.identity(), (oldValue, newValue) -> newValue));
        for (int roleId : roleIds) {
            if (oldMap.remove(roleId) == null) {
                relSysUserRoleService.create(new RelSysUserRole(roleId,userId,username));
            }
        }
        relSysUserRoleService.delete(oldMap.values());
    }


}
